/*******************************************************************************
 * Level Master 2000
 * Copyright (C) 2010 Christian Herzog
 * For more information see http://code.google.com/p/levelmaster2000/
 *
 * This file is licensed under the terms of the MIT license, see
 * http://www.opensource.org/licenses/mit-license.php for further information.
 ******************************************************************************/

#include "LevelManager.h"
#include "ui_LevelManager.h"

#include "Logger.h"
#include "widgets/LevelTreeWidgetItem.h"

#include <QDomDocument>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>

LevelManager::LevelManager( QWidget *parent )
    : QDockWidget( parent )
{
    init();
}

LevelManager::~LevelManager()
{
    foreach( LevelDescription *levelDesc, levelDescriptions )
    {
        delete levelDesc;
    }

    levelDescriptions.clear();
}

void LevelManager::init()
{
    Ui::levelManagerWidget uiLevelManagerWidget;
    uiLevelManagerWidget.setupUi( this );

    this->setVisible( true );

    levelTree = this->findChild<QTreeWidget*>( "levelTree" );

    QPushButton *loadLevelButton = this->findChild<QPushButton*>( "loadLevelButton" );
    connect( loadLevelButton,
             SIGNAL( pressed() ),
             this,
             SLOT( loadSelectedLevel() ) );
}

void LevelManager::setWorkspaceDir( QString dir )
{
    QString oldDir = workspaceDir;

    workspaceDir = dir;

    int success = loadLevelDescriptions();
    if( success < 0 )
    {
        //If failed to load workspaceDir, set it back to oldDir:
        workspaceDir = oldDir;
    }
    else
    {
        emit workspaceChanged( workspaceDir );
    }
}

void LevelManager::setWorkspace()
{
    QString dir = QFileDialog::getExistingDirectory( this,
                                            tr( "Pick Root Directory" ),
                                            workspaceDir ) ;

    if( dir != ""
        && dir != workspaceDir )
    {
        setWorkspaceDir( dir );
    }
}

void LevelManager::show()
{
    this->setVisible( true );
    this->setFloating( true );
}

void LevelManager::saveCurrentLevel()
{
    emit requestSaveCurrentLevel( currentLevel->index, currentLevel->name );
}

void LevelManager::onSaveLevel( QString levelState )
{
    //TODO: save to current level file
    if( currentLevel->files.count() > 1 )
    {
        QMessageBox::critical( this,
                               "Error saving level",
                               "Couldn't save level file, because leveldescription consits of more than one file!" );
    }

    if( currentLevel->files.count() == 1 )
    {
        QFile file( workspaceDir + "/" + currentLevel->files[0] );
        file.open( QIODevice::WriteOnly | QIODevice::Text );
        QTextStream out(&file);
        out << levelState;
        file.close();
    }
}

void LevelManager::loadSelectedLevel()
{
    QList<QTreeWidgetItem*> items = levelTree->selectedItems();

    //Note: only one item selectable anyway...
    foreach( QTreeWidgetItem *item, items )
    {
        LevelTreeWidgetItem* levelItem = dynamic_cast<LevelTreeWidgetItem*>( item );

        if( levelItem )
        {
            emit loadLevel( levelItem->levelDescription->index,
                            levelItem->levelDescription->name );

            currentLevel = levelItem->levelDescription;
        }
    }
}

void LevelManager::buildLevelDescriptionTree()
{
    levelTree->clear();

    foreach( LevelDescription *levelDesc, levelDescriptions )
    {
        LevelTreeWidgetItem *item = new LevelTreeWidgetItem( 0, levelDesc );
        item->setText( 0, levelDesc->name );
        levelTree->addTopLevelItem( item );
    }

    levelTree->sortItems( 0, Qt::AscendingOrder );
}

int LevelManager::loadLevelDescriptions()
{
    //Clear all old level descriptions:
    foreach( LevelDescription *levelDesc, levelDescriptions )
    {
        delete levelDesc;
    }

    levelDescriptions.clear();

    //Load levelDescriptions.xml:
    QDomDocument levelDescriptionDoc( "levelDescriptionDoc" );
    QFile file( workspaceDir + "/levelDescriptions.xml" );

    if( !file.open( QIODevice::ReadOnly ) )
    {
        Logger::instance()->addLogMessage( Logger::LL_ERROR,
                               "LevelManager::loadLevelDescriptions",
                               "Failed to load loadLevelDescriptions.xml! ( Couldn't find "
                               + workspaceDir + "/levelDescriptions.xml)" );
        return -1;
    }

    if( !levelDescriptionDoc.setContent( &file ) )
    {
        file.close();
        Logger::instance()->addLogMessage( Logger::LL_ERROR,
                               "LevelManager::loadLevelDescriptions",
                               "Could not set content of levelDescriptions.xml!" );
        return -2;
    }

    file.close();

    QDomElement root = levelDescriptionDoc.documentElement();
    if( root.tagName().toLower() != "leveldescriptions" )
    {
        Logger::instance()->addLogMessage( Logger::LL_ERROR,
                               "LevelManager::loadLevelDescriptions",
                               "Root tag not of type loadLevelDescriptions!" );
        return -3;
    }

    //Everything is valid, now we can parse the levelDescription file:
    QDomElement levelNode = root.firstChildElement();
    while( !levelNode.isNull() )
    {
        if( levelNode.tagName().toLower() == "level" )
        {
            LevelDescription *levelDescription = new LevelDescription();

            levelDescription->index = levelNode.attribute( "index" ).toInt();
            levelDescription->name = levelNode.attribute( "name" );

            //Parse children (group and file nodes):
            QDomElement childNode = levelNode.firstChildElement();
            while( !childNode.isNull() )
            {
                if( childNode.tagName().toLower() == "group" )
                {
                    levelDescription->groups.push_back( childNode.attribute( "name" ) );
                }

                else if( childNode.tagName().toLower() == "file" )
                {
                    //Currently, we only support 1 level file!
                    if( levelDescription->files.size() == 1 )
                    {
                        Logger::instance()->addLogMessage( Logger::LL_ERROR,
                                               "LevelManager::loadLevelDescriptions",
                                               "ONLY 1 LEVEL FILE SUPPORTED!" );

                        QMessageBox::critical( this,
                                               "LevelManager::loadLevelDescriptions",
                                               "Error in " + workspaceDir + "/levelDescriptions.xml"
                                               + "\nOnly 1 Level file supported!" );

                    }
                    levelDescription->files.push_back( childNode.attribute( "filename" ) );
                }

                childNode = childNode.nextSiblingElement();
            }

            levelDescriptions.push_back( levelDescription );
        }
        else
        {
            Logger::instance()->addLogMessage( Logger::LL_ERROR,
                                   "LevelManager::loadLevelDescriptions",
                                   "Not a level tag! (" + levelNode.tagName() + ")" );
        }

        levelNode = levelNode.nextSiblingElement();
    }

    buildLevelDescriptionTree();

    return 1;
}



